;(function(window) {

    'use strict';

    /**
     * Equation of a line.
     */
    function lineEq(y2, y1, x2, x1, currentVal) {
        // y = mx + b
        var m = (y2 - y1) / (x2 - x1),
            b = y1 - m * x1;

        return m * currentVal + b;
    }

    function TextFx(el) {
        this.el = el;
        this._init();
    }

    TextFx.prototype.effects = {
        'fx1' : {
            in: {
                duration: 1000,
                delay: function(el, index) { return 75+index*40; },
                easing: 'easeOutElastic',
                elasticity: 650,
                opacity: {
                    value: 1,
                    easing: 'easeOutExpo',
                },
                translateY: ['50%','0%']
            },
            out: {
                duration: 400,
                delay: function(el, index) { return index*40; },
                easing: 'easeOutExpo',
                opacity: 0,
                translateY: '-100%'
            }
        },
        'fx2' : {
            in: {
                duration: 700,
                delay: function(el, index) { return index*50; },
                easing: 'easeOutCirc',
                opacity: 1,
                translateX: function(el, index) {
                    return [(50+index*10),0]
                }
            },
            out: {
                duration: 0,
                opacity: 0
            }
        },
        'fx3' : {
            in: {
                duration: 800,
                delay: function(el, index) { return index*50; },
                easing: 'easeOutElastic',
                opacity: 1,
                translateY: function(el, index) {
                    return index%2 === 0 ? ['-80%', '0%'] : ['80%', '0%'];
                }
            },
            out: {
                duration: 800,
                delay: function(el, index) { return index*50; },
                easing: 'easeOutExpo',
                opacity: 0,
                translateY: function(el, index) {
                    return index%2 === 0 ? '80%' : '-80%';
                }
            }
        },
        'fx4' : {
            in: {
                duration: 700,
                delay: function(el, index) { return (el.parentNode.children.length-index-1)*80; },
                easing: 'easeOutElastic',
                opacity: 1,
                translateY: function(el, index) {
                    return index%2 === 0 ? ['-80%', '0%'] : ['80%', '0%'];
                },
                rotateZ: [90,0]
            },
            out: {
                duration: 500,
                delay: function(el, index) { return (el.parentNode.children.length-index-1)*80; },
                easing: 'easeOutExpo',
                opacity: 0,
                translateY: function(el, index) {
                    return index%2 === 0 ? '80%' : '-80%';
                },
                rotateZ: function(el, index) {
                    return index%2 === 0 ? -25 : 25;
                }
            }
        },
        'fx5' : {
            perspective: 1000,
            in: {
                duration: 700,
                delay: function(el, index) { return 550+index*50; },
                easing: 'easeOutQuint',
                opacity: {
                    value: 1,
                    easing: 'linear',
                },
                translateY: ['-150%','0%'],
                rotateY: [180,0]
            },
            out: {
                duration: 700,
                delay: function(el, index) { return index*60; },
                easing: 'easeInQuint',
                opacity: {
                    value: 0,
                    easing: 'linear',
                },
                translateY: '150%',
                rotateY: -180
            }
        },
        'fx6' : {
            in: {
                duration: 600,
                easing: 'easeOutQuart',
                opacity: 1,
                translateY: function(el, index) {
                    return index%2 === 0 ? ['-40%', '0%'] : ['40%', '0%'];
                },
                rotateZ: [10,0]
            },
            out: {
                duration: 0,
                opacity: 0
            }
        },
        'fx7' : {
            in: {
                duration: 250,
                delay: function(el, index) { return 200+index*25; },
                easing: 'easeOutCubic',
                opacity: 1,
                translateY: ['-50%','0%']
            },
            out: {
                duration: 250,
                delay: function(el, index) { return index*25; },
                easing: 'easeOutCubic',
                opacity: 0,
                translateY: '50%'
            }
        },
        'fx8' : {
            in: {
                duration: 400,
                delay: function(el, index) { return 150+(el.parentNode.children.length-index-1)*20; },
                easing: 'easeOutQuad',
                opacity: 1,
                translateY: ['100%','0%']
            },
            out: {
                duration: 400,
                delay: function(el, index) { return (el.parentNode.children.length-index-1)*20; },
                easing: 'easeInOutQuad',
                opacity: 0,
                translateY: '-100%'
            }
        },
        'fx9' : {
            perspective: 1000,
            origin: '50% 100%',
            in: {
                duration: 400,
                delay: function(el, index) { return index*50; },
                easing: 'easeOutSine',
                opacity: 1,
                rotateY: [-90,0]
            },
            out: {
                duration: 200,
                delay: function(el, index) { return index*50; },
                easing: 'easeOutSine',
                opacity: 0,
                rotateY: 45
            }
        },
        'fx10' : {
            in: {
                duration: 1000,
                delay: function(el, index) { return 100+index*30; },
                easing: 'easeOutElastic',
                elasticity: anime.random(400, 700),
                opacity: 1,
                rotateZ: function(el, index) {
                    return [anime.random(20,40),0];
                }
            },
            out: {
                duration: 0,
                opacity: 0
            }
        },
        'fx11' : {
            perspective: 1000,
            origin: '50% 100%',
            in: {
                duration: 400,
                delay: function(el, index) { return 200+index*20; },
                easing: 'easeOutExpo',
                opacity: 1,
                rotateY: [-90,0]
            },
            out: {
                duration: 400,
                delay: function(el, index) { return index*20; },
                easing: 'easeOutExpo',
                opacity: 0,
                rotateY: 90
            }
        },
        'fx12' : {
            perspective: 1000,
            origin: '50% 100%',
            in: {
                duration: 400,
                delay: function(el, index) { return 200+index*30; },
                easing: 'easeOutExpo',
                opacity: 1,
                rotateX: [90,0]
            },
            out: {
                duration: 400,
                delay: function(el, index) { return index*30; },
                easing: 'easeOutExpo',
                opacity: 0,
                rotateX: -90
            }
        },
        'fx13' : {
            in: {
                duration: 800,
                easing: 'easeOutExpo',
                opacity: 1,
                translateY: function(el, index) {
                    var p = el.parentNode,
                        lastElOffW = p.lastElementChild.offsetWidth,
                        firstElOffL = p.firstElementChild.offsetLeft,
                        w = p.offsetWidth - lastElOffW - firstElOffL - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
                        tyVal = lineEq(0, 200, firstElOffL + w/2, firstElOffL, el.offsetLeft);

                    return [Math.abs(tyVal)+50+'%','0%'];
                },
                rotateZ: function(el, index) {
                    var p = el.parentNode,
                        lastElOffW = p.lastElementChild.offsetWidth,
                        firstElOffL = p.firstElementChild.offsetLeft,
                        w = p.offsetWidth - lastElOffW - p.firstElementChild.offsetLeft - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
                        rz = lineEq(90, -90,firstElOffL + w, firstElOffL, el.offsetLeft);

                    return [rz,0];
                }
            },
            out: {
                duration: 500,
                easing: 'easeOutExpo',
                opacity: 0,
                translateY: '-150%'
            }
        },
        'fx14' : {
            in: {
                duration: 500,
                easing: 'easeOutExpo',
                delay: function(el, index) { return 200+index*30; },
                opacity: 1,
                rotateZ: [20,0],
                translateY: function(el, index) {
                    var p = el.parentNode,
                        lastElOffW = p.lastElementChild.offsetWidth,
                        firstElOffL = p.firstElementChild.offsetLeft,
                        w = p.offsetWidth - lastElOffW - firstElOffL - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
                        tyVal = lineEq(-130, -60, firstElOffL+w, firstElOffL, el.offsetLeft);

                    return [Math.abs(tyVal)+'%','0%'];
                }
            },
            out: {
                duration: 400,
                easing: 'easeOutExpo',
                delay: function(el, index) { return (el.parentNode.children.length-index-1)*30; },
                opacity: 0,
                rotateZ: 20,
                translateY: function(el, index) {
                    var p = el.parentNode,
                        lastElOffW = p.lastElementChild.offsetWidth,
                        firstElOffL = p.firstElementChild.offsetLeft,
                        w = p.offsetWidth - lastElOffW - firstElOffL - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
                        tyVal = lineEq(-60, -130, firstElOffL+w, firstElOffL, el.offsetLeft);

                    return tyVal+'%';
                }
            }
        },
        'fx15' : {
            perspective: 1000,
            in: {
                duration: 400,
                delay: function(el, index) { return 100+index*50; },
                easing: 'easeOutExpo',
                opacity: 1,
                rotateX: [110,0]
            },
            out: {
                duration: 400,
                delay: function(el, index) { return index*50; },
                easing: 'easeOutExpo',
                opacity: 0,
                rotateX: -110
            }
        },
        'fx16' : {
            in: {
                duration: function(el, index) { return anime.random(800,1000) },
                delay: function(el, index) { return anime.random(0,75) },
                easing: 'easeInOutExpo',
                opacity: 1,
                translateY: ['-300%','0%'],
                rotateZ: function(el, index) { return [anime.random(-50,50), 0]; }
            },
            out: {
                duration: function(el, index) { return anime.random(800,1000) },
                delay: function(el, index) { return anime.random(0,80) },
                easing: 'easeInOutExpo',
                opacity: 0,
                translateY: '300%',
                rotateZ: function(el, index) { return anime.random(-50,50); }
            }
        },
        'fx17' : {
            in: {
                duration: 650,
                easing: 'easeOutQuint',
                delay: function(el, index) { return 450+(el.parentNode.children.length-index-1)*30; },
                opacity: 1,
                translateX: function(el, index) {
                    return [-1*el.offsetLeft,0];
                }
            },
            out: {
                duration: 1,
                delay: 400,
                opacity: 0
            }
        },
        'fx18' : {
            in: {
                duration: 800,
                delay: function(el, index) { return 600+index*150; },
                easing: 'easeInOutQuint',
                opacity: 1,
                scaleY: [8,1],
                scaleX: [0.5,1],
                translateY: ['-100%','0%']
            },
            out: {
                duration: 800,
                delay: function(el, index) { return index*150; },
                easing: 'easeInQuint',
                opacity: 0,
                scaleY: {
                    value: 8,
                    delay: function(el, index) { return 100+index*150; },
                },
                scaleX: 0.5,
                translateY: '100%'
            }
        }
    };

    TextFx.prototype._init = function() {
        // Split word(s) into letters/spans.
        charming(this.el, {classPrefix: 'letter'});
        this.letters = [].slice.call(this.el.querySelectorAll('span'));
        this.lettersTotal = this.letters.length;
    };

    TextFx.prototype.show = function(effect, callback) {
        arguments.length ? this._animate('in', effect, callback) : this.letters.forEach(function(letter) { letter.style.opacity = 1; });
    };

    TextFx.prototype.hide = function(effect, callback) {
        if( arguments.length ) {
            this._animate('out', effect, callback);
        }
        else {
            anime.remove(this.letters);
            this.letters.forEach(function(letter) { letter.style.opacity = 0; })
        }
    };

    TextFx.prototype._animate = function(direction, effect, callback) {
        var effecSettings = typeof effect === 'string' ? this.effects[effect] : effect;

        if( effecSettings.perspective != undefined ) {
            this.el.style.WebkitPerspective = this.el.style.perspective = effecSettings.perspective + 'px';
        }
        if( effecSettings.origin != undefined ) {
            this.letters.forEach(function(letter) {
                letter.style.WebkitTransformOrigin = letter.style.transformOrigin = effecSettings.origin;
            });
        }

        // Custom effect
        var iscustom = this._checkCustomFx(direction, effect, callback);

        var animOpts = effecSettings[direction];
        animOpts.targets = this.letters;

        if( !iscustom ) {
            animOpts.complete = callback;
        }

        anime(animOpts);
    };

    /**
     * Extra stuff for an effect.. this is just an example for effect 17.
     * TODO! (for now, just some quick way to implement something different only for fx17)
     */
    TextFx.prototype._checkCustomFx = function(direction, effect, callback) {
        var custom = typeof effect === 'string' && effect === 'fx17' && direction === 'out';

        if( custom ) {
            var tmp = document.createElement('div');
            tmp.style.width = tmp.style.height = '100%';
            tmp.style.top = tmp.style.left = 0;
            tmp.style.background = '#e24b1e';
            tmp.style.position = 'absolute';
            tmp.style.WebkitTransform = tmp.style.transform = 'scale3d(0,1,1)';
            tmp.style.WebkitTransformOrigin = tmp.style.transformOrigin = '0% 50%';
            this.el.appendChild(tmp);
            var self = this;
            anime({
                targets: tmp,
                duration: 400,
                easing: 'easeInOutCubic',
                scaleX: [0,1],
                complete: function() {
                    tmp.style.WebkitTransformOrigin = tmp.style.transformOrigin = '100% 50%';
                    anime({
                        targets: tmp,
                        duration: 400,
                        easing: 'easeInOutCubic',
                        scaleX: [1,0],
                        complete: function() {
                            self.el.removeChild(tmp);
                            if( typeof callback === 'function' ) {
                                callback();
                            }
                        }
                    });
                }
            });
        }

        return custom;
    };

    window.TextFx = TextFx;

})(window);/**
 * Created by oswasia on 17/8/18.
 */
